﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Collections.Specialized;
using System.Web.Mvc.Ajax;

namespace TestWeb.Helpers
{
    /// <summary>
    /// The extension class for pagination
    /// </summary>
    public static class GridPagerExtension
    {
        #region Methods

        /// <summary>
        /// The extension method for pagination
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="properties">The properties for pagination will be wrapped in this object</param>
        /// <returns></returns>
        public static string GridPager(this HtmlHelper helper, GridPagerProperties properties)
        {
            return GenerateLinks(helper, properties);
        }

        /// <summary>
        /// The method for excuting the pagination
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="properties">The properties for pagination will be wrapped in this object</param>
        /// <returns></returns>
        private static string GenerateLinks(HtmlHelper helper, GridPagerProperties properties)
        {
            TagBuilder pagerDiv = new TagBuilder("div") { };
            pagerDiv.MergeAttributes(new Dictionary<string, string> { { "class", "pager" } });

            TagBuilder ulDiv = new TagBuilder("div");
            ulDiv.MergeAttributes(new Dictionary<string, string> { { "class", "pagerItem" } });

            TagBuilder ul = new TagBuilder("ul");

            if (properties.TotalPage > 1)
            {
                //create the previous tag
                if (properties.CurrentPageIndex > 1)
                {
                    properties.LinkText = "<";
                    properties.PageIndex = properties.CurrentPageIndex - 1;
                    //add previous tag
                    ul.InnerHtml += GetNavItem(helper, properties).ToString();
                }

                for (int page = 1; page <= properties.TotalPage; page++)
                {
                    //create paging tags
                    properties.LinkText = page.ToString();
                    properties.PageIndex = page;
                    //create tag
                    TagBuilder tag = GetNavItem(helper, properties);
                    if (page == properties.CurrentPageIndex)
                    {
                        tag.Attributes.Add("class", "selected");
                    }

                    TagBuilder label = new TagBuilder("label")
                    {
                        InnerHtml = HttpUtility.HtmlEncode("...")
                    };
                    label.MergeAttributes(new Dictionary<string, string> { { "text", "..." } });


                    if (properties.TotalPage > 11)
                    {
                        if (properties.CurrentPageIndex < 7)
                        {
                            //beginning
                            if (page < 9 || ((properties.TotalPage - page) < 3))
                                ul.InnerHtml += tag.ToString();
                            else if (page == 10)
                                ul.InnerHtml += label.ToString();
                        }
                        else if (properties.CurrentPageIndex >= (properties.TotalPage - 7))
                        {
                            //end
                            if (page < 2 || (page >= properties.TotalPage - 9))
                                ul.InnerHtml += tag.ToString();
                            else if (page == 2)
                                ul.InnerHtml += label.ToString();
                        }
                        else
                        {
                            //middle
                            if (page < 2)
                                ul.InnerHtml += tag.ToString();
                            else if (page == 2)
                                ul.InnerHtml += label.ToString();
                            else if ((page >= (properties.CurrentPageIndex - 4)) && (page <= (properties.CurrentPageIndex + 4)))
                                ul.InnerHtml += tag.ToString();
                            else if (page == properties.CurrentPageIndex + 5)
                                ul.InnerHtml += label.ToString();
                            else if (page >= properties.TotalPage - 2)
                                ul.InnerHtml += tag.ToString();
                        }
                    }
                    else
                        ul.InnerHtml += tag.ToString();
                }

                //create the next tag
                if (properties.CurrentPageIndex < properties.TotalPage)
                {
                    properties.LinkText = ">";
                    properties.PageIndex = properties.CurrentPageIndex + 1;
                    //add previous tag
                    ul.InnerHtml += GetNavItem(helper, properties).ToString();
                }
            }

            ulDiv.InnerHtml += ul;
            pagerDiv.InnerHtml += ulDiv;

            // create the total items tag
            TagBuilder countDiv = new TagBuilder("div")
            {
                InnerHtml = String.Format("{0} items", properties.RecordCount)
            };
            countDiv.MergeAttributes(new Dictionary<string, string> { { "class", "totalrecords" }, { "id", "grid_totalrecords" } });

            pagerDiv.InnerHtml += countDiv.ToString();

            return pagerDiv.ToString();
        }

        /// <summary>
        /// Builder the navigation for each page index
        /// </summary>
        /// <param name="html"></param>
        /// <param name="properties">The properties for pagination will be wrapped in this object</param>
        /// <returns></returns>
        private static TagBuilder GetNavItem(HtmlHelper html, GridPagerProperties properties)
        {
            UrlHelper urlHelper = ((Controller)html.ViewContext.Controller).Url;
            string url = string.Empty;

            switch (properties.GridPagerType)
            {
                case GridPagerType.LoaiTinTuc:
                    url = urlHelper.Action(properties.ActionName, properties.Controller,
                        new { Page = properties.PageIndex });
                break;
            }
            
            TagBuilder actionLink = new TagBuilder("a");
            actionLink.SetInnerText(properties.LinkText);
            actionLink.MergeAttributes(new Dictionary<string, string> { { "href", url } });
            
            TagBuilder linkTag = new TagBuilder("li")
            {
                InnerHtml = actionLink.ToString()
            };

            return linkTag;
        }

        #endregion
    }

    /// <summary>
    /// Properties for pagination
    /// </summary>
    public class GridPagerProperties
    {
        #region Properties

        /// <summary>
        /// The number of record will be found
        /// </summary>
        public int RecordCount { get; set; }

        /// <summary>
        /// The current page index
        /// </summary>
        public int CurrentPageIndex { get; set; }

        /// <summary>
        /// The page index will be actived, it is not current page index
        /// </summary>
        public int PageIndex { get; set; }

        /// <summary>
        /// The total page
        /// </summary>
        public int TotalPage { get; set; }

        /// <summary>
        /// List of parameter values
        /// </summary>
        public List<string> ParamValues { get; set; }

        /// <summary>
        /// Specified for each type
        /// </summary>
        public GridPagerType GridPagerType { get; set; }

        /// <summary>
        /// Display for the link
        /// </summary>
        public string LinkText { get; set; }

        /// <summary>
        /// The name of action will be navigated
        /// </summary>
        public string ActionName { get; set; }

        /// <summary>
        /// The name of controller
        /// </summary>
        public string Controller { get; set; }

        #endregion

        #region Constructor

        /// <summary>
        /// Default constructor
        /// </summary>
        public GridPagerProperties()
        {
            GridPagerType = GridPagerType.Default;
        }

        #endregion
    }

    /// <summary>
    /// For each specified type, this enum value will be assigned
    /// </summary>
    public enum GridPagerType
    {
        Default,
        NguoiDung,
        LoaiTinTuc
    }
}
